/*
 * rc4.c
 *
 * Copyright (c) 1996-2000 Whistle Communications, Inc.
 * All rights reserved.
 * 
 * Subject to the following obligations and disclaimer of warranty, use and
 * redistribution of this software, in source or object code forms, with or
 * without modifications are expressly permitted by Whistle Communications;
 * provided, however, that:
 * 1. Any and all reproductions of the source or object code must include the
 *    copyright notice above and the following disclaimer of warranties; and
 * 2. No rights are granted, in any manner or form, to use Whistle
 *    Communications, Inc. trademarks, including the mark "WHISTLE
 *    COMMUNICATIONS" on advertising, endorsements, or otherwise except as
 *    such appears in the above copyright notice or in the software.
 * 
 * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
 * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
 * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
 * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
 * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
 * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
 * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
 * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
 * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
 * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
 * OF SUCH DAMAGE.
 *
 * $FreeBSD: src/sys/crypto/rc4/rc4.c,v 1.2.2.1 2000/04/18 04:48:31 archie Exp $
 */

#include "RC4.h"

/*
 * RC4 functions
 */
 
/* Initialize State[256] to the identity permutation. */
void RC4::initialize() 
{
	int i;
	
	for(i=0; i<256; i++) 
    {
		state[i] = i;
	}
}

/* Swap array elements i=State[i] and b=State[j]. */
void RC4::swap(u_char *i, u_char *j) 
{
	u_char temp;
	
	temp = *i;
	*i = *j;
	*j = temp;
}

/* Key scheduling algorithm. Swap array elements based on the key. */
void RC4::ksa() 
{
	int i, j=0;
	
	for(i=0; i<256; i++) 
    {
		j = (j + state[i] + rc4_key[i%rc4_key_len]) % 256;
		swap(&state[i], &state[j]);
	}
}

/* Pseudo-random number generator: Generate the keystream. */
u_char * RC4::prng(int msglength) 
{
	int i=0, j=0, k;
	
	u_char *keystream;
	
	keystream = (u_char *)malloc(sizeof(u_char)*msglength);
	
	for(k=0; k<msglength; k++) {
		i = (i+1) % 256;
		j = (j+state[i]) % 256;
		
		swap(&state[i], &state[j]);
		
		keystream[k] = state[(state[i]+state[j]) % 256];
	}
	return keystream;
}

/* Encrypt or Decrypt */
void RC4::rc4(u_char *input, u_char *output, int len) 
{
	int i;
	u_char *keystream;
	
	initialize();
	ksa();
	keystream = prng(len);
	
	for(i=0; i<len; i++)
		output[i] = input[i] ^ keystream[i];
}

bool RC4::encrypt(u_char* data, u_char* pOut, int len )
{
    if (data == NULL || pOut == NULL || len == 0)
    {
        return false;
    }

    rc4(data, pOut, len);
    return true;
}

bool RC4::decrypt(u_char* data, u_char* pOut, int len)
{
    if (data == NULL || pOut == NULL || len == 0)
    {
        return false;
    }

    rc4(data, pOut, len);
    return true;
}

